package org.linlinjava.litemall.admin.aop;


import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.linlinjava.litemall.admin.annotation.repeat.RequestKeyParam;
import org.linlinjava.litemall.admin.annotation.repeat.RequestRepeatLock;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.concurrent.TimeUnit;

///**
// * @Author: penglingyu
// * @Date: 2024/3/28 14:43
// */
//@Aspect
//@Component
//@Slf4j
public class RequestRepeatLockAspect {

//    @Resource
//    private RedisTemplate<String,Object> redisTemplate;
//
//    //配置织⼊点
//    @Pointcut("@annotation(org.linlinjava.litemall.web.annotation.repeat.RequestRepeatLock)")
//    public void cachePointCut() {
//    }
//
//    @Around("cachePointCut()")
//    public Object doRequestRepeatLockAspect(ProceedingJoinPoint joinPoint) throws
//            Throwable {
//        // 1 获得重载后的⽅法名
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        Method method = joinPoint.getTarget().getClass()
//                .getMethod(signature.getName(),
//                        signature.getMethod().getParameterTypes());
//        // 2 确定⽅法名后获得该⽅法上⾯配置的注解 RequestRepeatLock
//        RequestRepeatLock requestRepeatLock = method.getAnnotation(RequestRepeatLock.class);
//        // 构造缓存唯⼀key
//        String cacheKey = getLockKey(joinPoint);
//        boolean isLock = setLock(cacheKey, requestRepeatLock.timeout(), requestRepeatLock.unit());
//        if (!isLock) {
//            return requestRepeatLock.message();
//        }
//        return joinPoint.proceed();
//    }
//
//    /**
//     * 按钮提交，加锁逻辑
//     *
//     * @param key
//     * @param expire
//     * @return
//     */
//    public boolean setLock(String key, long expire, TimeUnit timeUnit) {
//        Boolean flag;
//        try {
//            // 原⼦⾏命令⼀个：set k1 v1 nx ex 10
//            flag = redisTemplate.execute(
//                    (RedisCallback<Boolean>) connection ->
//                            connection.set(key.getBytes(),
//                                    IdUtil.fastSimpleUUID().getBytes(), Expiration.from(expire, timeUnit),
//                                    RedisStringCommands.SetOption.ifAbsent()));
//            log.info("**********execute action:{} ", flag);
//            return flag;
//        } catch (Exception e) {
//            log.error("set redis occured an exception", e);
//        }
//        return false;
//    }
//
//    /**
//     * 唯⼀key业务规则获取
//     *
//     * @param joinPoint
//     * @return
//     */
//    public String getLockKey(ProceedingJoinPoint joinPoint) {
//        StringBuilder stringBuilder = new StringBuilder();
//        //获取连接点的⽅法签名对象
//        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        //Method对象
//        Method method = methodSignature.getMethod();
//        System.out.println("******method: " + method);
//        System.out.println("******method.getName(): " + method.getName());
//        //获取Method对象上的注解对象
//        RequestRepeatLock requestRepeatLock = method.getAnnotation(RequestRepeatLock.class);
//        //获取⽅法参数
//        final Object[] args = joinPoint.getArgs();
//        for (Object element : args) {
//            System.out.println("******args: " + element);
//        }
//        //获取Method对象上所有的注解
//        final Parameter[] parameters = method.getParameters();
//        System.out.println(parameters.length);
//        /* for (Parameter element : parameters) {
//        System.out.println("******parameters: " + element.getName());
//        }*/
//        for (int i = 0; i < parameters.length; i++) {
//            final RequestKeyParam keyParam = parameters[i].getAnnotation(RequestKeyParam.class);
//            //如果属性不是RequestKeyParam注解，则不处理
//            if (keyParam == null) {
//                continue;
//            }
//            //如果属性是RequestKeyParam注解，则拼接 连接符 "& + RequestKeyParam"
//            stringBuilder.append(requestRepeatLock.delimiter()).append(args[i]);
//        }
//        System.out.println("******stringBuilder拼接有RequestKeyParam注解: " + stringBuilder);
//        //注解@RequestKeyParam可以放在⽅法的参数上，
//        // 也可以放在对象的属性上，所以这⾥需要进⾏两次判断，⼀次是获取⽅法上的注解，⼀次是获取对象⾥⾯属性上的注解。
//        //如果⽅法上没有加RequestKeyParam注解
//        if (StringUtils.isEmpty(stringBuilder.toString())) {
//            //获取⽅法上的多个注解（为什么是两层数组：因为第⼆层数组是只有⼀个元素的数组）
//            final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
//            //循环注解
//            for (int i = 0; i < parameterAnnotations.length; i++) {
//                final Object object = args[i];
//                //获取注解类中所有的属性字段
//                final Field[] fields = object.getClass().getDeclaredFields();
//                for (Field field : fields) {
//                    //判断字段上是否有RequestKeyParam注解
//                    final RequestKeyParam annotation = field.getAnnotation(RequestKeyParam.class);
//                    //如果没有，跳过
//                    if (annotation == null) {
//                        continue;
//                    }
//                    //如果有，设置Accessible为true（为true时可以使⽤反射访问私有变量，否则不能访问私有变量）
//                    field.setAccessible(true);
//                    //如果属性是RequestKeyParam注解，则拼接 连接符" & + RequestKeyParam"
//                    stringBuilder.append(requestRepeatLock.delimiter()).append(ReflectionUtils.getField(field, object));
//                }
//            }
//            System.out.println("******stringBuilder拼接有RequestKeyParam注解: " + stringBuilder);
//        }
//        String userId = "";
//        if (requestRepeatLock.userKey()) {
//            userId = ""; // 获取⽤户id
//        }
//        // 构造唯⼀key
//        String key = SecureUtil.md5(userId + method.getName());
//        stringBuilder.append(key);
//        return requestRepeatLock.keyPrefix() + stringBuilder;
//    }






}
